﻿using HenuAlbum.Identity;
using HenuAlbum.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HenuAlbum.DbContext
{
    public class AppDbContext : IdentityDbContext<User, Role, int, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>
    {
        private readonly DbContextOptions<AppDbContext> _options;

        public DbSet<Resource> Resources { get; set; }

        public DbSet<GroupPicture> GroupPictures { get; set; }

        public DbSet<ResourceTag> ResourceTag { get; set; }      

        public DbSet<Carousel> Carousel { get; set; }
        public DbSet<Notification> Notifications { get; set; }
        public DbSet<HotRecommend> HotRecommend { get; set; }

        public DbSet<College> Colleges { get; set; }

        public DbSet<Major> Majors { get; set; }

        public DbSet<Class> Classes { get; set; }

        public DbSet<Album> Albums { get; set; }
        public DbSet<Comments> Comments { get; set; }

        public DbSet<PersonalAlbum> PersonalAlbums { get; set; }

        public DbSet<GroupAlbum> GroupAlbums { get; set; }

        public DbSet<SchoolAlbum> SchoolAlbums { get; set; }

        public DbSet<Grade> Grades { get; set; }

        public DbSet<UserLikeAlbum> UserLikeAlbum { get; set; }

        public DbSet<ClassAlbumView> ClassAlbumView { get; set; }

        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {
            _options = options;
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<ClassAlbumView>(e =>
            {
                e.HasNoKey();
                e.ToView(nameof(ClassAlbumView));
            });

            int stringMaxLength = 64;
            // User IdentityRole and IdentityUser in case you haven't extended those classes
            modelBuilder.Entity<Role>(x => x.Property(m => m.Name).HasMaxLength(stringMaxLength));
            modelBuilder.Entity<Role>(x => x.Property(m => m.NormalizedName).HasMaxLength(stringMaxLength));
            modelBuilder.Entity<User>(x => x.Property(m => m.NormalizedUserName).HasMaxLength(stringMaxLength));
            modelBuilder.Entity<UserLogin>(x => x.Property(m => m.LoginProvider).HasMaxLength(stringMaxLength));
            modelBuilder.Entity<UserLogin>(x => x.Property(m => m.ProviderKey).HasMaxLength(stringMaxLength));
            modelBuilder.Entity<UserToken>(x => x.Property(m => m.LoginProvider).HasMaxLength(stringMaxLength));
            modelBuilder.Entity<UserToken>(x => x.Property(m => m.Name).HasMaxLength(stringMaxLength));


            modelBuilder.Entity<RoleClaim>(builder =>
            {
                builder.HasOne(roleClaim => roleClaim.Role).WithMany(role => role.Claims).HasForeignKey(roleClaim => roleClaim.RoleId);
                builder.ToTable("RoleClaim");
            });

            modelBuilder.Entity<Role>(builder =>
            {
                builder.ToTable("Role");
            });

            modelBuilder.Entity<UserClaim>(builder =>
            {
                builder.HasOne(userClaim => userClaim.User).WithMany(user => user.Claims).HasForeignKey(userClaim => userClaim.UserId);
                builder.ToTable("UserClaim");
            });

            modelBuilder.Entity<UserLogin>(builder =>
            {
                builder.HasOne(userLogin => userLogin.User).WithMany(user => user.Logins).HasForeignKey(userLogin => userLogin.UserId);
                builder.ToTable("UserLogin");
            });

            modelBuilder.Entity<User>(builder =>
            {
                builder.ToTable("User");
                builder.HasMany(x => x.PersonalAlbums).WithOne(x => x.Creator).HasForeignKey(x => x.CreatorId);
                builder.HasMany(x => x.ManagedMajors).WithMany(x => x.Managers).UsingEntity(x => x.ToTable("MajorManagers"));
            });

            modelBuilder.Entity<UserRole>(builder =>
            {
                builder.HasOne(userRole => userRole.Role).WithMany(role => role.Users).HasForeignKey(userRole => userRole.RoleId);
                builder.HasOne(userRole => userRole.User).WithMany(user => user.Roles).HasForeignKey(userRole => userRole.UserId);
                builder.ToTable("UserRole");
            });

            modelBuilder.Entity<UserToken>(builder =>
            {
                builder.HasOne(userToken => userToken.User).WithMany(user => user.UserTokens).HasForeignKey(userToken => userToken.UserId);
                builder.ToTable("UserToken");
            });

            modelBuilder.Entity<College>(builder =>
            {
                builder.HasMany(x => x.Majors).WithOne(x => x.College).HasForeignKey(x => x.CollegeId);
            });

            modelBuilder.Entity<Major>(builder =>
            {
                builder.HasMany(x => x.Classes).WithOne(x => x.Major).HasForeignKey(x => x.MajorId);
            });

            modelBuilder.Entity<Class>(builder =>
            {
                builder.HasMany(x => x.Students).WithOne(x => x.Class).HasForeignKey(x => x.ClassId);
                builder.HasMany(x => x.PersonalAlbums).WithOne(x => x.Class).HasForeignKey(x => x.ClassId);
            });

            modelBuilder.Entity<Album>(builder =>
            {
                builder.HasMany(x => x.Resources).WithOne(x => x.Album).HasForeignKey(x => x.AlbumId);
                builder.HasMany(x => x.Comments).WithOne(x => x.Album).HasForeignKey(x => x.AlbumId);
            });

            modelBuilder.Entity<Grade>(builder =>
            {
                builder.HasIndex(x => x.Value).IsUnique();
                builder.HasMany(x => x.Classes).WithOne(x => x.Grade).HasForeignKey(x => x.GradeId);
            });

            modelBuilder.Entity<UserLikeAlbum>(builder =>
            {
                builder.HasOne(x => x.Album).WithMany(x => x.Like).HasForeignKey(x => x.AlbumId);
                builder.HasOne(x => x.User).WithMany(x => x.LikeAlbums).HasForeignKey(x => x.UserId);
                builder.HasKey(x => new { x.AlbumId, x.UserId });
                builder.HasIndex(x => x.AlbumId);
                builder.HasIndex(x => x.UserId);
            });

            modelBuilder.Entity<GroupPictureMember>(builder =>
            {
                builder.HasOne(x => x.GroupPicture).WithMany(x => x.Members).HasForeignKey(x => x.GroupPictureId);
                builder.HasIndex(x => new { x.Row, x.Column }).IsUnique();
            });

        }
    }
}
